﻿module CPFD.Test

open Monad
open Core

//////////////////////////////////////////////////////////////////////
// Test
//////////////////////////////////////////////////////////////////////

let sample1 = cp {
        let! a = newVar [1..4]
        let! b = newVar [1..4]
        do! different a b
        return! labelling [a; b]
    }

runFD sample1 |> printf "sample1: %A\n"

let sample2 = cp {
        let! vars = newVars 3 [1..4]
        do! allDifferent vars
        return! labelling vars
    }

runFD sample2 |> printf "sample2: %A\n"

let sample3 = cp {
        let! a = newVar [1..9]
        let! b = newVar [1..3]
        let! c = newVar [1..2]
        do! hasValue a 7
        return! labelling [a;b;c]
    }

runFD sample3 |> printf "sample3: %A\n"

let sample4 = cp {
        let! a = newVar [1..9]
        let! b = newVar [2..7]
        do! same a b
        return! labelling [a;b]
    }

runFD sample4 |> printf "sample4: %A\n"

let sample5 = cp {
        let! a = newVar [1..10]
        let! b = newVar [1..10]
        do! compareBy (fun av bv -> av + bv = 8) a b
        return! labelling [a;b]
    }

runFD sample5 |> printf "sample5: %A\n"

let threeEqual = 
    let threeEqualConstraint xs = cp {
        match xs with
        | [x;y;z] -> 
            let! xv = lookup x
            let! yv = lookup y
            let! zv = lookup z
            let i = Set.intersect xv yv |> Set.intersect zv             
            do! cp.Guard(Set.isEmpty i |> not)
            if i <> xv then
                do! update x i
            if i <> yv then
                do! update y i
            if i <> zv then
                do! update z i  
        | _ -> raise(new System.Exception())              
    }
    addMultiVariableConstraint threeEqualConstraint

//let rec enumParams xs =
//    seq {
//        match xs with
//        | ((_::_)::_) ->
//            yield List.map List.head xs |> List.concat
//            yield! enumParams (List.map List.tail xs)
//    }

//let genparams xs = 
//    match xs with
//    | (x,v)::rest -> 
//let eval e =
//    let evalConstraint xs = cp {
//        for x in xs do
//            let! xv = lookup x
//            yield (x, xv)        
//        let! vs = mapM lookup xs
//
//    }
//    addMultiVariableConstraint evalConstraint

let sample6 = cp {
        let! vars = newVars 3 [1..5]
        do! threeEqual vars
        return! labelling vars
    }

runFD sample6 |> printf "sample6: %A\n"
